package elephant.servers.gameserver;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import elephant.Server;
import elephant.servers.gameserver.connect.GameServerConnect;
import elephant.servers.gameserver.core.GameRequestDispatch;
import elephant.servers.gameserver.core.GameRoom;
import elephant.servers.gameserver.service.GameService;
import elephant.servers.gameserver.service.GameServiceManager;
import elephant.servers.gameserver.service.MethodInfo;
import elephant.servers.gameserver.session.GameSession;
import elephant.servers.gameserver.session.GameSessionManager;
import elephant.servers.gameserver.session.SessionLifecycleListener;
import elephant.util.ObjectPrinter;
import elephant.util.PerformMonitor;


/**
 * 
 * @author icecooly
 *
 */
public class GameServer implements Server{
	//
	//
	private static Logger logger=LoggerFactory.getLogger(GameServer.class);
	//
	private GameServerConnect connect;
	private GameServiceManager serviceManager;
	private GameSessionManager sessionManager;
	private GameRequestDispatch requestDispatch;
	private PerformMonitor performMonitor;
	//
	public GameServer(){
		serviceManager=new GameServiceManager();
		sessionManager=new GameSessionManager();
		requestDispatch=new GameRequestDispatch(this,serviceManager);
		connect=new GameServerConnect(sessionManager,requestDispatch);
		performMonitor=new PerformMonitor();
	}
	//
	public void init() throws Exception {
		if(logger.isInfoEnabled()){
			logger.info(getClass().getSimpleName()+" init");
		}
		connect.init();
	}
	//
	@Override
	public void start() throws Exception{
		if(logger.isInfoEnabled()){
			logger.info(getClass().getSimpleName()+" start");
		}
		connect.start();
	}
	//
	@Override
	public void stop() throws Exception{
		if(logger.isInfoEnabled()){
			logger.info(getClass().getSimpleName()+" stop");
		}
		connect.stop();
	}
	//
	public int getPort() {
		return connect.getPort();
	}
	//
	public void setPort(int port) {
		connect.setPort(port);
	}
	//
	public void registerService(GameService gs){
		serviceManager.registerService(gs);
	}
	//
	public int getSessionCount(){
		return sessionManager.getSessionCount();
	}
	//
	public int getMaxSessionCount(){
		return sessionManager.getMaxSessionCount();
	}
	//
	public PerformMonitor getPerformMonitor() {
		return performMonitor;
	}
	//
	public void broadcast(String serviceId,Object payload){
		sessionManager.broadcast(serviceId, payload);
	}
	//
	public void broadcast(String serviceId,short payload,int excludeSessionId){
		sessionManager.broadcast(serviceId, payload, excludeSessionId);
	}
	//
	public void registerSessionLifecycleListener(SessionLifecycleListener l){
		sessionManager.registerSessionLifecycleListener(l);
	}
	//
	public void removeSessionLifecycleListener(SessionLifecycleListener l){
		sessionManager.removeSessionLifecycleListener(l);
	}
	//
	public GameSession getSessionByPrincipal(String principal){
		return sessionManager.getSessionByPrincipal(principal);
	}
	/**
	 * 
	 */
	public GameSession getSessionById(int id){
		return sessionManager.getSessionById(id);
	}
	/**
	 * setup session principal info,user agent is an option but recommend
	 */
	public void setPrincipal(GameSession s,String principal,String userAgent){
		sessionManager.setPrincipal(s, principal, userAgent);
	}
	/***/
	public GameRoom createRoom(String id){
		return sessionManager.createRoom(id);
	}
	//
	@Override
	public String dump() {
		ObjectPrinter op=new ObjectPrinter();
		op.section(this.getClass().getSimpleName());
		op.print("port",getPort());
		op.print("sessionTimeout",sessionManager.getSessionTimeout());	
		op.section("services");
		List<MethodInfo> list=new ArrayList<MethodInfo>(serviceManager.getMethodMap().values());
		list.forEach((info)->{
			String name=info.method.getName();
			if(info.syncOnSession){
				name+="[syncOnSession]";
			}
			if(info.disableResponse){
				name+="[disableResponse]";
			}
			op.print(info.method.getDeclaringClass().getSimpleName(),name);
		});		
		return op.toString();
	}
}
